home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
CBASE102.ARJ
/
CBDDLP.Y
< prev
next >
Wrap
Text File
|
1991-09-23
|
25KB
|
885 lines
/* Copyright (c) 1989 Citadel */
/* All Rights Reserved */
/* definition section --------------------------------------------------------*/
%{
/* #ident "@(#)cbddlp.y 1.6 - 91/09/23" */
#include <ansi.h>
/* local headers */
#include "cbddlp.h"
#ifdef DEBUG
#define DBPRINT { \
fprintf(stderr, "%s[%d].\n", __FILE__, __LINE__); \
}
#else
#define DBPRINT
#endif
%}
/* declaration section -------------------------------------------------------*/
%union {
int keyword;
char * buf;
}
%token <keyword> COMPOUND CONTAINS DATAFILE KEY INDEXFILE RECORD UNIQUE
%token <buf> ELEMC IDENTIFIER STRING
/* rule section --------------------------------------------------------------*/
%%
/* data definition language */
ddl : stmt
| ddl stmt
;
/* generic statement */
stmt : /* blank line */
| datafile
| indexfile
| record
;
/* date file statement */
datafile: DATAFILE STRING CONTAINS IDENTIFIER ';' {
#ifdef DEBUG
fprintf(stderr, "Line %d: DATAFILE \"%s\" CONTAINS %s;\n", yylineno, $2, $4);
#endif
/* add slot to data file table */
ddldfv = (ddldf_t *)realloc(ddldfv, (dfc + 1) * sizeof(*ddldfv));
if (ddldfv == NULL) {
yyerror("out of memory");
return -1;
}
memset(ddldfv + dfc, 0, sizeof(*ddldfv));
ddldfv[dfc].filename = $2;
ddldfv[dfc].record = $4;
++dfc;
}
;
/* index file statement */
indexfile: INDEXFILE STRING CONTAINS IDENTIFIER ';' {
#ifdef DEBUG
fprintf(stderr, "Line %d: INDEXFILE \"%s\" CONTAINS %s;\n", yylineno, $2, $4);
#endif
/* add slot to index file table */
ddlifv = (ddlif_t *)realloc(ddlifv, (ifc + 1) * sizeof(*ddlifv));
if (ddlifv == NULL) {
yyerror("out of memory");
return -1;
}
memset(ddlifv + ifc, 0, sizeof(*ddlifv));
ddlifv[ifc].filename = $2;
ddlifv[ifc].key = $4;
++ifc;
}
;
/* record statement */
record : RECORD IDENTIFIER '{' fldlst '}' ';' {
int fld = 0;
#ifdef DEBUG
fprintf(stderr, "Line %d: RECORD %s { fldlst };\n", yylineno, $2);
#endif
recname = $2;
ddlputh(hfp, recname, fldc, ddlfldv);
ddlputi(ifp, recname, fldc, ddlfldv);
/* free memory allocated for current record */
free(recname);
recname = NULL;
for (fld = 0; fld < fldc; ++fld) {
ddlfldv[fld].flags = 0;
free(ddlfldv[fld].type);
ddlfldv[fld].type = NULL;
if (isalloc(ddlfldv[fld].ctype)) {
free(ddlfldv[fld].ctype);
}
ddlfldv[fld].ctype = NULL;
free(ddlfldv[fld].name);
ddlfldv[fld].name = NULL;
if (ddlfldv[fld].elemc != NULL) free(ddlfldv[fld].elemc);
ddlfldv[fld].elemc = NULL;
}
fldc = 0;
}
;
/* field list */
fldlst : fld
| fldlst fld
;
/* field */
fld : fqlst IDENTIFIER IDENTIFIER ELEMC ';' {
#ifdef DEBUG
fprintf(stderr, "Line %d: fqlst %s %s [%s];\n", yylineno, $2, $3, $4);
#endif
/* add slot to field table */
ddlfldv = (ddlfld_t *)realloc(ddlfldv, (fldc + 2) * sizeof(*ddlfldv));
if (ddlfldv == NULL) {
yyerror("out of memory");
return -1;
}
memset(ddlfldv + fldc + 1, 0, sizeof(*ddlfldv));
ddlfldv[fldc].type = $2;
ddlfldv[fldc].ctype = ctype(ddlfldv[fldc].type);
if (ddlfldv[fldc].ctype == NULL) {
yyerror("Undefined cbase data type");
return -1;
}
ddlfldv[fldc].name = $3;
ddlfldv[fldc].elemc = $4;
++fldc;
}
| fqlst IDENTIFIER IDENTIFIER ';' {
#ifdef DEBUG
fprintf(stderr, "Line %d: fqlst %s %s;\n", yylineno, $2, $3);
#endif
/* add slot to field table */
ddlfldv = (ddlfld_t *)realloc(ddlfldv, (fldc + 2) * sizeof(*ddlfldv));
if (ddlfldv == NULL) {
yyerror("out of memory");
return -1;
}
memset(ddlfldv + fldc + 1, 0, sizeof(*ddlfldv));
ddlfldv[fldc].type = $2;
ddlfldv[fldc].ctype = ctype(ddlfldv[fldc].type);
if (ddlfldv[fldc].ctype == NULL) {
yyerror("Undefined cbase data type");
return -1;
}
ddlfldv[fldc].name = $3;
ddlfldv[fldc].elemc = NULL;
++fldc;
}
| fqlst IDENTIFIER ':' IDENTIFIER IDENTIFIER ELEMC ';' {
#ifdef DEBUG
fprintf(stderr, "Line %d: fqlst %s:%s %s %s;\n", yylineno, $2, $4, $5, $6);
#endif
/* add slot to field table */
ddlfldv = (ddlfld_t *)realloc(ddlfldv, (fldc + 2) * sizeof(*ddlfldv));
if (ddlfldv == NULL) {
yyerror("out of memory");
return -1;
}
memset(ddlfldv + fldc + 1, 0, sizeof(*ddlfldv));
ddlfldv[fldc].type = $2;
ddlfldv[fldc].ctype = $4;
ddlfldv[fldc].name = $5;
ddlfldv[fldc].elemc = $6;
++fldc;
}
| fqlst IDENTIFIER ':' IDENTIFIER IDENTIFIER ';' {
/* add slot to field table */
ddlfldv = (ddlfld_t *)realloc(ddlfldv, (fldc + 2) * sizeof(*ddlfldv));
if (ddlfldv == NULL) {
yyerror("out of memory");
return -1;
}
memset(ddlfldv + fldc + 1, 0, sizeof(*ddlfldv));
ddlfldv[fldc].type = $2;
ddlfldv[fldc].ctype = $4;
ddlfldv[fldc].name = $5;
ddlfldv[fldc].elemc = NULL;
++fldc;
}
;
/* field qualifier list */
fqlst : /* none */
| fqlst fq
;
/* field qualifier */
fq : COMPOUND {
#ifdef DEBUG
fprintf(stderr, "Line %d: COMPOUND\n", yylineno);
#endif
yyerror("compound keys not yet implemented");
return -1;
}
| KEY {
#ifdef DEBUG
fprintf(stderr, "Line %d: KEY\n", yylineno);
#endif
ddlfldv[fldc].flags |= CB_FKEY;
}
| UNIQUE {
#ifdef DEBUG
fprintf(stderr, "Line %d: UNIQUE\n", yylineno);
#endif
ddlfldv[fldc].flags |= CB_FUNIQ;
}
;
%%
/* subroutine section --------------------------------------------------------*/
/* ansi headers */
#include <errno.h>
#ifdef AC_STDDEF
#include <stddef.h>
#endif
#include <stdio.h>
#ifdef AC_STDLIB
#include <stdlib.h>
#endif
#ifdef AC_STRING
#include <string.h>
#endif
/* library headers */
#include <bool.h>
#include <cbase.h>
/* local headers */
#include "basstr.h"
#include "cbddlp.h"
/* constants */
#define PROGNAME "cbddlp" /* default program name */
#define USAGE "usage: %s ddlfile\n" /* usage message */
/* global definitions */
char * progname = PROGNAME; /* program name */
FILE * hfp = NULL; /* .h file stream */
FILE * ifp = NULL; /* .i file stream */
char * recname = NULL; /* record name */
int dfc = 0; /* data file count */
ddldf_t * ddldfv = NULL; /* ddl data file table */
int ifc = 0; /* index file count */
ddlif_t * ddlifv = NULL; /* ddl index file table */
int fldc = 0; /* field count */
ddlfld_t * ddlfldv = NULL; /* ddl field table */
const char * const typtbl[] = { /* cbase/C data type table */
"t_char", "char", /* 0 */
"t_charv", "char", /* 1 */
"t_uchar", "unsigned char", /* 2 */
"t_ucharv", "unsigned char", /* 3 */
"t_short", "short", /* 4 */
"t_shortv", "short", /* 5 */
"t_ushort", "unsigned short", /* 6 */
"t_ushortv", "unsigned short", /* 7 */
"t_int", "int", /* 8 */
"t_intv", "int", /* 9 */
"t_uint", "unsigned int", /* 10 */
"t_uintv", "unsigned int", /* 11 */
"t_long", "long", /* 12 */
"t_longv", "long", /* 13 */
"t_ulong", "unsigned long", /* 14 */
"t_ulongv", "unsigned long", /* 15 */
"t_float", "float", /* 16 */
"t_floatv", "float", /* 17 */
"t_double", "double", /* 18 */
"t_doublev", "double", /* 19 */
"t_ldouble", "long double", /* 20 */
"t_ldoublev", "long double", /* 21 */
"t_pointer", "void *", /* 22 */
"t_pointerv", "void *", /* 23 */
"t_string", "char", /* 24 */
"t_cistring", "char", /* 25 */
"t_binary", "unsigned char", /* 26 */
};
/*man---------------------------------------------------------------------------
NAME
cbddlp - cbase data definition language processor
SYNOPSIS
cbddlp ddlfile
DESCRIPTION
The cbddlp command processes cbase data definition language (DDL)
files. A cbase database can be specified in a DDL file, which is
then processed using cbddlp to generate the C files required by
cbase to manipulate that database. cbddlp requires that DDL
files have the suffix ".ddl". The C files generated are given
the same name as the DDL file except for the suffix; a .h and a
.i file are generated. The .h file must be included by every
module accessing the database, while the .i file must be included
by exactly one module of every program that accesses the database.
There are three types of DDL statements: data file, index file,
and record. The syntax for the record statement is
record recname {
[[unique ]key] dbtype fldname[\\[elemc\\]];
...
};
recname is the name of the record. dbtype is the database data
type of the field. fldname is the name of the field, and must be
unique for a given database. elemc specifies the number of
elements for array data types; this may be any C expression valid
for defining the size of a static array. The key keyword
specifies that an index is to be maintained on this field. The
unique keyword specifies that the keys in this index must be
unique. Multiple records can be defined in the same DDL file.
User-defined data types may also be specified in a DDL file, but
require an additional piece of information. For the predefined
data types, cbddlp knows what the corresponding C data type is
(t_string : char, t_int : int, etc.). But for user-defined data
types, this must be explicitly specified. The syntax for this is
as follows.
[[unique ]key] dbtype:ctype fldname[\[elemc\]];
where dbtype is a user-defined database data type and ctype is
the corresponding C data type. ctype must consist of only one
identifier; if the C data type consists of multiple identifiers
(e.g., long double), either #define or typedef must be used to
reduce it to one identifier (e.g., typedef long double ldouble).
The syntax for the data file statement is
data file "filename" contains recname;
filename is the name of the file in which recname records are to
be stored. The data file statement must precede its associated
record statement.
The syntax for the index file statement is
index file "filename" contains keyname;
filename is the name of the file in which keyname keys are to be
indexed. The index file statement must precede the record
statement containing the associated key.
C comments may appear in DDL files wherever white space is
allowed, with the exception of within the keyword pairs "data
file" and "index file". C preprocessor statements may also be
placed in DDL files, but cannot currently span multiple lines,
nor can comments on the same line as a preprocessor statement;
any line beginning with the # character (excluding any leading
white space) will be passed directly through to the generated .h
file.
In the headers generated by cbddlp, a macro for the record name
is constructed by converting all lower case letters in the record
name to capitals. A macro is also defined for each field in the
same fashion. The initial characters (up to four) of the first
field name of a record preceding the first underscore are used as
a prefix for the field count macro and field definition list.
This prefix must be unique for all records in a database. The
field count macro identifier is constructed by converting this
prefix to capitals and appending FLDC. The field definition list
identifier is constructed by appending fldv to the prefix.
EXAMPLE
Below is given an example DDL file for a rolodeck database
consisting of a single record.
/* constants *\/
#define NAME_MAX (40) /* max name length *\/
#define ADDR_MAX (40) /* max address length *\/
#define NOTELIN_MAX (4) /* note lines *\/
#define NOTECOL_MAX (40) /* note columns *\/
/* file assignments *\/
data file "rolodeck.dat" contains rolodeck;
index file "rdcont.ndx" contains rd_contact;
index file "rdcomp.ndx" contains rd_company;
record rolodeck { /* rolodeck record *\/
unique key t_string
rd_contact[NAME_MAX]; /* contact name *\/
t_string rd_title[41]; /* contact title *\/
key t_string rd_company[NAME_MAX]; /* company name *\/
t_string rd_addr[81]; /* address *\/
t_string rd_city[26]; /* city *\/
t_string rd_state[3]; /* state *\/
t_string rd_zip[11]; /* zip code *\/
t_string rd_phone[13]; /* phone number *\/
t_string rd_ext[5]; /* phone extension *\/
t_string rd_fax[13]; /* fax number *\/
t_string rd_notes[NOTELIN_MAX * NOTECOL_MAX];
/* notes *\/
};
If the name of this DDL file was rolodeck.ddl, the generated C
files would be rolodeck.h and rolodeck.i. The cbase name macro
would be ROLODECK (the record identifier capitalized). The field
count macro would be RDFLDC, and the field definition list would
be rdfldv. The rolodeck would be therefore be opened (for
writing) with the C statement
cbopen(ROLODECK, "r+", RDFLDC, rdfldv);
The phone number from the current record would be read from the
database with
cbgetrf(cbp, RD_PHONE, buf);
NOTES
For a make utility to automatically process DDL files without an
explicit rule for each one, suffix rules defining the creation of
the data definition header files from a DDL file can be added to
the makefile. For the standard UNIX make, the following
instructions would be inserted near the beginning of the
makefile.
# suffix rules
.SUFFIXES: .ddl .h .i
.ddl.h:
cbddlp $<
.ddl.i:
cbddlp $<
The exact procedure for other make utilities varies.
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
int main(int argc, char *argv[])
#else
int main(argc, argv)
int argc;
char *argv[];
#endif
{
char * dbname = NULL; /* database name */
char * udbname = NULL; /* upper case database name */
char * ddlfile = NULL; /* ddl filename */
FILE * ddlfp = NULL; /* ddl file stream */
char * hfile = NULL; /* .h filename */
char * ifile = NULL; /* .i filename */
size_t len = 0; /* string length */
char * p1 = NULL; /* gp pointers */
char * p2 = NULL;
/* process command line */
if (argc > 0) { /* program name */
progname = *argv;
--argc;
++argv;
}
if (argc < 1) { /* ddl filename */
fprintf(stderr, USAGE, progname);
exit(EXIT_FAILURE);
}
ddlfile = *argv;
--argc;
++argv;
if (argc != 0) {
fprintf(stderr, USAGE, progname);
exit(EXIT_FAILURE);
}
/* construct output filenames */
p1 = strrchr(ddlfile, PATHDLM); /* remove path prefix */
if (p1 == NULL) {
p1 = ddlfile;
} else {
++p1;
}
p2 = strrchr(p1, '.'); /* remove dot suffix */
if (p2 == NULL) {
fprintf(stderr, "%s: Input file must have .ddl suffix.\n", progname);
exit(EXIT_FAILURE);
}
if (strcmp(p2, ".ddl") != 0) {
fprintf(stderr, "%s: Input file must have .ddl suffix.\n", progname);
exit(EXIT_FAILURE);
}
len = p2 - p1; /* length w/o suffix */
hfile = (char *)malloc(len + 2 + 1); /* .h file name */
if (hfile == NULL) {
perror("out of memory");
exit(EXIT_FAILURE);
}
strncpy(hfile, p1, len);
strncpy(hfile + len, ".h", 2);
hfile[len + 2] = NUL;
ifile = (char *)malloc(len + 2 + 1); /* .i file name */
if (ifile == NULL) {
perror("out of memory");
exit(EXIT_FAILURE);
}
strncpy(ifile, p1, len);
strncpy(ifile + len, ".i", 2);
ifile[len + 2] = NUL;
dbname = (char *)malloc(len + 1); /* database name */
if (dbname == NULL) {
perror("out of memory");
exit(EXIT_FAILURE);
}
strncpy(dbname, p1, len);
dbname[len] = NUL;
udbname = (char *)malloc(len + 1); /* upper case database name */
if (udbname == NULL) {
perror("out of memory");
exit(EXIT_FAILURE);
}
cvtss(udbname, dbname, CVT_UPPER, len);
udbname[len] = NUL;
/* allocate first slot in each ddl table */
ddldfv = (ddldf_t *)calloc((size_t)1, sizeof(*ddldfv));
/* data file table */
if (ddldfv == NULL) {
perror("out of memory");
exit(EXIT_FAILURE);
}
ddlifv = (ddlif_t *)calloc((size_t)1, sizeof(*ddlifv));
/* index file table */
if (ddlifv == NULL) {
perror("out of memory");
exit(EXIT_FAILURE);
}
ddlfldv = (ddlfld_t *)calloc((size_t)1, sizeof(*ddlfldv));
/* field table */
if (ddlfldv == NULL) {
perror("out of memory");
exit(EXIT_FAILURE);
}
/* open files */
ddlfp = fopen(ddlfile, "r"); /* ddl file */
if (ddlfp == NULL) {
perror("opening ddl file");
exit(EXIT_FAILURE);
}
hfp = fopen(hfile, "w"); /* .h file */
if (hfp == NULL) {
perror("opening .h file");
exit(EXIT_FAILURE);
}
ifp = fopen(ifile, "w"); /* .i file */
if (ifp == NULL) {
perror("opening .i file");
exit(EXIT_FAILURE);
}
/* redirect lex input to ddl stream */
yyin = ddlfp;
/* write multiple include #ifndefs */
fprintf(hfp, "#ifndef H_%s\t/* prevent multiple includes */\n", udbname);
fprintf(hfp, "#define H_%s\n\n", udbname);
fprintf(ifp, "#ifndef I_%s\t/* prevent multiple includes */\n", udbname);
fprintf(ifp, "#define I_%s\n\n", udbname);
/* write #includes */
fputs("/* libray headers */\n", hfp); /* .h file */
fputs("#include <cbase.h>\n\n", hfp);
fputs("#include <ansi.h>\n", ifp); /* .i file */
fputs("\n/* ansi headers */\n", ifp);
fputs("#ifdef AC_STDDEF\n", ifp);
fputs("#include <stddef.h>\n", ifp);
fputs("#endif\n", ifp);
fputs("\n/* libray headers */\n", ifp);
fputs("#include <cbase.h>\n", ifp);
fputs("\n/* local headers */\n", ifp);
fprintf(ifp, "#include \"%s\"\n\n", hfile);
/* process ddl file */
if (yyparse()) {
fprintf(stderr, "Fatal error processing %s.\n", ddlfile);
exit(EXIT_FAILURE);
}
if (ferror(hfp)) {
fprintf(stderr, "Error writing %s: ", hfile);
perror("");
exit(EXIT_FAILURE);
}
if (ferror(ifp)) {
fprintf(stderr, "Error writing %s: ", ifile);
perror("");
exit(EXIT_FAILURE);
}
/* write multiple include #endifs */
fprintf(hfp, "#endif /* #ifndef H_%s */\n", udbname);
fprintf(ifp, "#endif /* #ifndef I_%s */\n", udbname);
/* close files */
if (fclose(ddlfp) == EOF) {
fprintf(stderr, "Error closing %s: ", ddlfile);
perror("");
exit(EXIT_FAILURE);
}
if (fclose(hfp) == EOF) {
fprintf(stderr, "Error closing %s: ", hfile);
perror("");
exit(EXIT_FAILURE);
}
if (fclose(ifp) == EOF) {
fprintf(stderr, "Error closing %s: ", ifile);
perror("");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
/* ctype: get C data type from cbase data type */
#ifdef AC_PROTO
char *ctype(const char *type)
#else
char *ctype(type)
const char *type;
#endif
{
int i = 0;
for (i = 0; i < nelems(typtbl); i += 2) {
if (strcmp(typtbl[i], type) == 0) {
return typtbl[i + 1];
}
}
return NULL;
}
/* fpctype: put C type */
#ifdef AC_PROTO
int fpctype(FILE *fp, const char *type)
#else
int fpctype(fp, type)
FILE *fp;
const char *type;
#endif
{
int i = 0;
for (i = 0; i < nelems(typtbl); i += 2) {
if (strcmp(typtbl[i], type) == 0) {
fputs(typtbl[i + 1], fp);
return 0;
}
}
return -1;
}
/* fpdatafile: file print data file name */
#ifdef AC_PROTO
int fpdatafile(FILE *fp, const char *recname)
#else
int fpdatafile(fp, recname)
FILE *fp;
const char *recname;
#endif
{
int i = 0;
for (i = 0; i < dfc; ++i) {
if (strcmp(ddldfv[i].record, recname) == 0) {
fprintf(fp, ddldfv[i].filename);
return 0;
}
}
return -1;
}
/* fpndxfile: file print index file name */
#ifdef AC_PROTO
int fpndxfile(FILE *fp, const char *keyname)
#else
int fpndxfile(fp, keyname)
FILE *fp;
const char *keyname;
#endif
{
int i = 0;
for (i = 0; i < ifc; ++i) {
if (strcmp(ddlifv[i].key, keyname) == 0) {
fprintf(fp, ddlifv[i].filename);
return 0;
}
}
return -1;
}
/* isalloc: is ctype allocated? */
#ifdef AC_PROTO
bool isalloc(const char *ctype)
#else
bool isalloc(ctype)
const char *ctype;
#endif
{
int i = 0;
for (i = 1; i < nelems(typtbl); i += 2) {
if (typtbl[i] == ctype) {
return FALSE;
}
}
return TRUE;
}
/* tmpupr: temporary upper case string conversion */
#ifdef AC_PROTO
char *tmpupr(const char *s)
#else
char *tmpupr(s)
const char *s;
#endif
{
static char uprstr[81];
cvtss(uprstr, s, CVT_UPPER, sizeof(uprstr));
uprstr[sizeof(uprstr) - 1] = NUL;
return uprstr;
}
/* warning: print warning message */
#ifdef AC_PROTO
void warning(const char *s, const char *t)
#else
void warning(s, t)
const char *s;
const char *t;
#endif
{
fprintf(stderr, "%s: %s", progname, s);
if (t != NULL) {
fprintf(stderr, " %s", t);
}
fprintf(stderr, " near line %d.\n", yylineno);
return;
}
/* yyerror: yacc error message */
#ifdef AC_PROTO
int yyerror(const char *s)
#else
int yyerror(s)
const char *s;
#endif
{
warning(s, NULL);
return 0;
}
/* global data for ddlput functions */
static char prefix[PREFIX_MAX + 1]; /* identifier prefix */
static char uprefix[PREFIX_MAX + 1]; /* prefix in upper case */
/* ddlputh: write to .h file */
#ifdef AC_PROTO
int ddlputh(FILE *fp, const char *recname, int fldc, const ddlfld_t fldv[])
#else
int ddlputh(fp, recname, fldc, fldv)
FILE *fp;
const char *recname;
int fldc;
const ddlfld_t fldv[];
#endif
{
int fld = 0; /* field number */
char * p = NULL; /* gp char pointer */
#ifdef DEBUG
/* validate arguments */
if (fp == NULL || recname == NULL || fldc < 1 || fldv == NULL) {
errno = EINVAL;
return -1;
}
#endif
/* record name */
fputs("/* record name */\n", fp);
fprintf(fp, "#define %s\t\"", tmpupr(recname));
if (fpdatafile(fp, recname) == -1) {
fprintf(stderr, "No data file name specified for record %s.\n", recname);
return -1;
}
fputs("\"\n\n", fp);
/* extract identifier prefix from first field name */
strncpy(prefix, fldv[0].name, sizeof(prefix));
prefix[sizeof(prefix) - 1] = NUL;
p = strchr(prefix, '_');
if (p != NULL) {
*p = NUL;
}
cvtss(uprefix, prefix, CVT_UPPER, sizeof(uprefix));
uprefix[sizeof(uprefix) - 1] = NUL;
/* record definition */
fprintf(fp, "/* %s record definition */\n", recname);
fprintf(fp, "typedef struct %s {\n", recname);
for (fld = 0; fld < fldc; ++fld) {
fputc('\t', fp);
fputs(fldv[fld].ctype, fp);
fprintf(fp, " %s", fldv[fld].name);
if (fldv[fld].elemc != NULL) {
fprintf(fp, "[%s]", fldv[fld].elemc);
}
fputs(";\n", fp);
}
fprintf(fp, "} %s_t;\n\n", recname);
/* field names */
fprintf(fp, "/* field names for record %s */\n", recname);
for (fld = 0; fld < fldc; ++fld) {
fprintf(fp, "#define %s", tmpupr(fldv[fld].name));
if (strlen(fldv[fld].name) < 8) { /* for tabs set at 8 */
fputc('\t', fp);
}
fprintf(fp, "\t(%d)\n", fld);
}
fprintf(fp, "#define %sFLDC\t\t(%d)\n\n", uprefix, fldc);
/* field definition list declaration */
fprintf(fp, "/* field definition list for record %s */\n", recname);
fprintf(fp, "extern cbfield_t %sfldv[%sFLDC];\n\n", prefix, uprefix);
return 0;
}
/* ddlputi: write to .i file */
#ifdef AC_PROTO
int ddlputi(FILE *fp, const char *recname, int fldc, const ddlfld_t fldv[])
#else
int ddlputi(fp, recname, fldc, fldv)
FILE *fp;
const char *recname;
int fldc;
const ddlfld_t fldv[];
#endif
{
int fld = 0; /* field number */
/* field definition list definition */
fprintf(fp, "/* field definition list for record %s */\n", recname);
fprintf(fp, "cbfield_t %sfldv[] = {\n", prefix);
for (fld = 0; fld < fldc; ++fld) {
fputs("\t{\n", fp);
fprintf(fp, "\t\toffsetof(struct %s, %s),\n", recname, fldv[fld].name);
fprintf(fp, "\t\tsizeofm(struct %s, %s),\n", recname, fldv[fld].name);
fprintf(fp, "\t\t%s,\n", fldv[fld].type);
if (fldv[fld].flags & CB_FKEY) {
fprintf(fp, "\t\tCB_FKEY");
if (fldv[fld].flags & CB_FUNIQ) {
fprintf(fp, " | CB_FUNIQ");
}
fputs(",\n\t\t\"", fp);
if (fpndxfile(fp, fldv[fld].name) == -1) {
fprintf(stderr, "No index file name specified for key %s.\n", fldv[fld].name);
}
fputs("\"\n", fp);
} else {
fputs("\t\t0,\n\t\tNULL\n", fp);
}
fprintf(fp, "\t},\n");
}
fprintf(fp, "};\n\n");
return 0;
}